﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CefSharp.OffScreen;
using CefSharp;
using System.Drawing;
using System.Net;
using System.IO;

namespace Chen.CefWebKit
{
    public class AdvanceWebKit
    {
        ChromiumWebBrowser wb;
        string HtmlCode;
        string Cachepath = "";
        NewClient nc;
        public AdvanceWebKit(string CachePathName = "Cache")
        {
            Cachepath = CachePathName;
            var browserSettings = new BrowserSettings();
            browserSettings.WindowlessFrameRate = 1;
            var setting = new CefSharp.CefSettings();
            setting.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36";
            if (!Cef.IsInitialized)
            {
                Cef.Initialize(setting);
            }
            var requestContextSettings = new RequestContextSettings { CachePath = CachePathName };
            var requestContext = new RequestContext(requestContextSettings);
            wb = new ChromiumWebBrowser("", browserSettings, requestContext);
            while (!wb.IsBrowserInitialized) { }
            Cef.GetGlobalCookieManager().SetStoragePath(@".\" + CachePathName + @"\", true);
            HtmlCode = "";
            nc = new NewClient(Directory.GetCurrentDirectory() + @"\" + CachePathName + @"\Cookies");

        }
        /// <summary>
        /// 截取浏览器页面
        /// </summary>
        public async void SaveScreenShot()
        {
            if (!Directory.Exists("./" + Cachepath + "/image/"))
            {
                Directory.CreateDirectory("./" + Cachepath + "/image/");
            }
            System.Drawing.Bitmap Timage = await wb.ScreenshotAsync(true);
            string date = DateTime.Now.ToString("yyyyMMddhhmmff");
            Timage.Save("./" + Cachepath + "/image/" + date + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
        }
        /// <summary>
        /// 获得浏览器BITMAP
        /// </summary>
        /// <returns></returns>
        public Bitmap GetScreenShot()
        {
            Bitmap Timage = wb.ScreenshotOrNull();
            return Timage;
        }
        /// <summary>
        /// 根据URL获取渲染后的HTML代码
        /// </summary>
        /// <param name="url">链接</param>
        /// <returns></returns>
        public String GetHtmlByUrl(string url)
        {
            Task Tload = LoadPageAsync(wb, url);
            Tload.Wait();
            Task<string> Thtml = wb.GetBrowser().MainFrame.GetSourceAsync();
            Thtml.Wait();
            HtmlCode = Thtml.Result;
            return HtmlCode;
        }
        /// <summary>
        /// 获得当前页面的HTML代码,确认在获取前读取过页面
        /// </summary>
        /// <returns></returns>
        public String GetHtml()
        {
            string Script = JavaScriptLibrary.QuerySelector("body");
            string result = RunScript(Script);
            return result;
            //Task<string> Thtml = wb.GetBrowser().MainFrame.GetSourceAsync();
            //Thtml.Wait();
            //HtmlCode = Thtml.Result;
            //return HtmlCode;
        }
        public string GetHtmlByQuery(string Selector)
        {
            string Script = JavaScriptLibrary.QuerySelector(Selector);
            string result = RunScript(Script);
            return result;
        }
        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <param name="name">名称</param>
        /// <param name="value">对应值</param>
        /// <param name="domain">所在域名</param>
        public void SetCookie(string name, string value, string domain, string path = "/")
        {
            string script =
                "seconds = 0;" +
                "var expires = \"\";" +
                "if (seconds != 0 ) {" +
                "var date = new Date();" +
                "date.setTime(date.getTime()+(seconds*1000));" +
                "expires = \"; expires = \"+date.toGMTString();}" +
                "document.cookie ='" + name + " = escape(" + value + "); path =" + path + "; domain =" + domain + "'";
            Task<JavascriptResponse> Tjs = wb.EvaluateScriptAsync(script);
            Tjs.Wait();
            string a = Tjs.Result.Result.ToString();
        }
        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <param name="cookies"></param>
        public void SetCookie(System.Net.Cookie[] cookies)
        {
            foreach (System.Net.Cookie i in cookies)
            {
                SetCookie(i.Name, i.Value, i.Domain);
            }
        }
        /// <summary>
        /// 获取当前页面Cookie
        /// </summary>
        /// <returns></returns>
        public string GetCookie()
        {
            string script = "document.cookie";
            Task<JavascriptResponse> Tjs = wb.EvaluateScriptAsync(script);
            Tjs.Wait();
            string Result = Tjs.Result.Result.ToString();
            return Result;
        }
        /// <summary>
        /// 浏览器打开页面
        /// </summary>
        /// <param name="url">链接</param>
        public void Load(string url)
        {
            Task t = LoadPageAsync(wb, url);
            t.Wait();
        }
        /// <summary>
        /// 渲染页面
        /// </summary>
        /// <param name="Source">Html代码</param>
        /// <param name="url">作为页面的URL地址</param>
        public void LoadSource(string Source, string url = "")
        {
            Task t = LoadHtmlAsync(wb, Source, url);
            t.Wait();
        }
        /// <summary>
        /// 运行JS代码
        /// </summary>
        /// <param name="script">JS代码</param>
        /// <returns></returns>
        public string RunScript(string script)
        {
            Task<JavascriptResponse> Tjs = wb.EvaluateScriptAsync(script);
            Tjs.Wait();
            if (Tjs.Result.Result != null)
            {
                string a = Tjs.Result.Result.ToString();
                return a;
            }
            return null;
        }
        /// <summary>
        /// 获得当前标签页的URL
        /// </summary>
        /// <returns></returns>
        public string GetUrl()
        {
            return wb.Address;
        }
        private static Task LoadPageAsync(IWebBrowser browser, string address = null)
        {
            var tcs = new TaskCompletionSource<bool>();

            EventHandler<LoadingStateChangedEventArgs> handler = null;
            handler = (sender, args) =>
            {
                //Wait for while page to finish loading not just the first frame
                if (!args.IsLoading)
                {
                    browser.LoadingStateChanged -= handler;
                    tcs.TrySetResult(true);
                }
            };

            browser.LoadingStateChanged += handler;

            if (!string.IsNullOrEmpty(address))
            {
                browser.Load(address);
            }
            return tcs.Task;
        }
        private static Task LoadHtmlAsync(IWebBrowser browser, string Html, string address = "")
        {
            var tcs = new TaskCompletionSource<bool>();

            EventHandler<LoadingStateChangedEventArgs> handler = null;
            handler = (sender, args) =>
            {
                //Wait for while page to finish loading not just the first frame
                if (!args.IsLoading)
                {
                    browser.LoadingStateChanged -= handler;
                    tcs.TrySetResult(true);
                }
            };

            browser.LoadingStateChanged += handler;

            if (!string.IsNullOrEmpty(address))
            {
                browser.LoadHtml(Html, address);
            }
            return tcs.Task;
        }
        #region WebClient 增强功能
        /// <summary>
        /// WebClient获取 BYTE
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public byte[] DownloadData(string url)
        {
            Task<byte[]> data = nc.Download(url);
            data.Wait();
            return data.Result;
        }
        /// <summary>
        /// WebClient 获取页面源代码
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public string DownloadHtmlCode(string url,Encoding encode=null)
        {
            if (encode == null)
            {
                encode = Encoding.UTF8;
            }
            var bytes = DownloadData(url);
            return encode.GetString(bytes);
        }
        /// <summary>
        /// WebClient Post提交数据获得反馈Byte[]
        /// </summary>
        /// <param name="url">链接</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public byte[] PostDataByte(string url, string value)
        {
            Task<byte[]> data = nc.PostDataByte(url, value);
            data.Wait();
            return data.Result;
        }
        /// <summary>
        /// WebClient Post提交数据获得反馈代码
        /// </summary>
        /// <param name="url">链接</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public string PostData(string url, string value)
        {
            Task<string> data = nc.PostData(url, value);
            data.Wait();
            return data.Result;
        }
        #endregion
    }
}
